package ig.finanzas;

import ig.util.ConexionServer;
import ig.util.ejb.IGBean;
import ig.util.excepciones.DatoInvalidoExcepcion;
import ig.util.excepciones.LogicaExcepcion;
//import java.io.FileNotFoundException;
import java.rmi.RemoteException;
import java.util.Date;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * Define la forma en que se paga utilizando una tasa. Como tasa de referencia
 * no puede especificarse una curva cero cupon.
 *
 * @author lfgarcia
 */
public class TasaPago implements RangoTiempo {

    /**
     * Representa la forma de una tasa fija simple
     */
    public static final byte FORMA_SIMPLE = 0;
    /**
     * Representa la forma Tasa + spread
     */
    public static final byte FORMA_ADICION = 1;
    /**
     * Representa la forma Tasa * spread
     */
    public static final byte FORMA_PRODUCTO = 2;
    /**
     * Representa la forma (1+Tasa)(1+spread)
     */
    public static final byte FORMA_MIXTA = 3;
    /**
     * Especifica la forma en que se operan los factores. @uml.property
     * name="forma"
     */
    private byte forma;
    /**
     * @uml.property name="spread"
     */
    private double spread;
    /**
     * Fecha a partir de la cual aplica la tasa de pago @uml.property
     * name="fechaInicio"
     */
    private Date fechaInicio;
    /**
     * Fecha hasta la cual aplica la tasa de pago @uml.property name="fechaFin"
     */
    private Date fechaFin;
    /**
     * @uml.property name="tasareferenciaPK" @uml.associationEnd
     */
    private TasaPK tasareferenciaPK;
    /**
     * @uml.property name="modalidadspread" @uml.associationEnd multiplicity="(1
     * 1)"
     */
    private Modalidad modalidadspread;
    /**
     * @uml.property name="modalidadpago" @uml.associationEnd multiplicity="(1
     * 1)"
     */
    private Modalidad modalidadpago;
    /**
     * Especifica si se liquida con la tasa vigente al fin de periodo, en caso
     * contrario se asume que se liquida con la tasa de principio de periodo.
     * @uml.property name="liquidaFinPeriodo"
     */
    private boolean liquidaFinPeriodo;

    /**
     * Constructor de una tasa de pago simple, es decir, una tasa de pago fija.
     *
     * @param spread
     * @param fechaInicio
     * @param fechaFin
     * @param modalidadtasa
     * @param nominalmodalidadspread
     * @param modalidadpago
     * @param nominalmodalidadpago
     * @throws DatoInvalidoExcepcion Si la fecha de inicio o fin son nulas, o si
     * las modalidades especificadas no poseen valores validos.
     */
    public TasaPago(double spread, Date fechaInicio, Date fechaFin,
            String modalidadtasa, boolean nominalmodalidadspread,
            String modalidadpago, boolean nominalmodalidadpago) throws DatoInvalidoExcepcion {

        if (fechaInicio == null) {
            throw new DatoInvalidoExcepcion("Fecha de inicio nula.");
        }

        if (fechaFin == null) {
            throw new DatoInvalidoExcepcion("Fecha fin nula.");
        }

        this.forma = FORMA_SIMPLE;
        this.spread = spread;
        this.fechaInicio = fechaInicio;
        this.fechaFin = fechaFin;
        this.modalidadspread = new Modalidad(modalidadtasa, nominalmodalidadspread);
        this.modalidadpago = new Modalidad(modalidadpago, nominalmodalidadpago);
        this.liquidaFinPeriodo = false;
    }

    /**
     * Constructor de una tasa de pago compleja. Utiliza una tasadereferencia y
     * un spread.
     *
     * @param forma
     * @param spread
     * @param fechaInicio
     * @param fechaFin
     * @param tasareferenciaPK
     * @param modalidadtasa
     * @param nominalmodalidadspread
     * @param modalidadpago
     * @param nominalmodalidadpago
     * @param liquidaFinPeriodo
     * @throws DatoInvalidoExcepcion Si la fecha de inicio o fin son nulas, o si
     * la forma de la tasa de pago no es valida, o si las modalidades
     * especificadas no poseen valores validos.
     */
    public TasaPago(byte forma, double spread, Date fechaInicio, Date fechaFin, TasaPK tasareferenciaPK,
            String modalidadtasa, boolean nominalmodalidadspread,
            String modalidadpago, boolean nominalmodalidadpago, boolean liquidaFinPeriodo)
            throws DatoInvalidoExcepcion {

        if (!(forma == FORMA_ADICION || forma == FORMA_PRODUCTO
                || forma == FORMA_MIXTA)) {
            throw new DatoInvalidoExcepcion("Valor para la forma de la tasa de pago no valido");
        }

        if (fechaInicio == null) {
            throw new DatoInvalidoExcepcion("Fecha de inicio nula.");
        }

        if (fechaFin == null) {
            throw new DatoInvalidoExcepcion("Fecha fin nula.");
        }

        this.forma = forma;
        this.spread = spread;
        this.fechaInicio = fechaInicio;
        this.fechaFin = fechaFin;
        this.tasareferenciaPK = tasareferenciaPK;
        this.modalidadspread = new Modalidad(modalidadtasa, nominalmodalidadspread);
        this.modalidadpago = new Modalidad(modalidadpago, nominalmodalidadpago);
        this.liquidaFinPeriodo = liquidaFinPeriodo;
    }

    /**
     * @return Returns the fechaInicio. @uml.property name="fechaInicio"
     */
    public Date getFechaInicio() {
        return fechaInicio;
    }

    /**
     * @return Returns the fechaFin. @uml.property name="fechaFin"
     */
    public Date getFechaFin() {
        return fechaFin;
    }

    /**
     * Obtiene el valor nominal especifico de la tasa de pago en un periodo.
     *
     * @param fechaAnalisis Fecha en la que se realiza el analisis.
     * @param fechaUltimoFlujo Fecha del ultimo pago de flujos.
     * @return
     * @throws Exception Si no fue posible encontrar la tasa
     * @throws DatoInvalidoExcepcion Si alguna de las fechas especificadas es
     * nula,
     * @throws LogicaExcepcion Si no se puede calcular el valor vigente de la
     * tasa o si el valor calculado es imaginario
     */
    public double tasaNominalPeriodo(Date fechaAnalisis, Date fechaUltimoFlujo) throws Exception, DatoInvalidoExcepcion, LogicaExcepcion {

        if (fechaAnalisis == null) {
            throw new DatoInvalidoExcepcion("La fecha de analisis es nula.");
        }

        if (fechaUltimoFlujo == null) {
            throw new DatoInvalidoExcepcion("La fecha del ultimo flujo es nula.");
        }


        double valortasa = 0;
        if (tasareferenciaPK != null) {
            try {
                /*
                 * InitialContext ctx = new InitialContext(prop); TasaHome home
                 * = (TasaHome)ctx.lookup("ig.finanzas.Tasa");
                 */
                Tasa tasa = new TasaBean().ejbFindByPrimaryKey(tasareferenciaPK);
                if (liquidaFinPeriodo) {
                    valortasa = tasa.obtenerValorVigenteA(fechaAnalisis, 0);
                } else {
                    valortasa = tasa.obtenerValorVigenteA(fechaUltimoFlujo, 0);
                }
                Modalidad modalidadTasa = tasa.getModalidadTasa();

                //cambio la expresion de la tasa a la expresion del spread(modalidadspread)
                valortasa = LibreriaOperacionesFinancieras.conversionTasas(valortasa, modalidadTasa, modalidadspread);
            } catch (RemoteException e) {
            } catch (NamingException e) {
                throw new Exception(e.toString());
            }

            if (forma == FORMA_ADICION) {
                valortasa = valortasa + spread / 100;
            }
            if (forma == FORMA_PRODUCTO) {
                valortasa = valortasa * spread / 100;
            }
            if (forma == FORMA_MIXTA) {
                valortasa = (1 + valortasa) * (1 + spread / 100);
            }
        } else {
            valortasa = spread / 100;
        }

        double valortasanominal = LibreriaOperacionesFinancieras.conversionTasas(
                valortasa, modalidadspread,
                new Modalidad(modalidadpago.getPeriodo(), modalidadpago.getModo(), true));

        return valortasanominal;
    }
}
